﻿using System;
using System.Collections.Generic;
using Mono.Cecil;

namespace CSLua
{

	// Token: 0x02000019 RID: 25
	public class OverloadAnalyzer
	{
		// Token: 0x060000D2 RID: 210 RVA: 0x00005370 File Offset: 0x00003570
		public static OverloadAnalyzer get(TypeDefinition def)
		{
			string fullName = def.luaGlobalIdentifier();
			OverloadAnalyzer cache;
			if (!OverloadAnalyzer.types.TryGetValue(fullName, out cache))
			{
				OverloadAnalyzer parentCache = null;
				if (def.BaseType != null)
				{
					parentCache = OverloadAnalyzer.get(def.BaseType.Resolve());
				}
				cache = new OverloadAnalyzer(def, parentCache);
				OverloadAnalyzer.types[fullName] = cache;
			}
			return cache;
		}

		// Token: 0x060000D3 RID: 211 RVA: 0x000053C4 File Offset: 0x000035C4
		public static string getMethodName(MethodReference method)
		{
			string methodId = getMethodId(method);
			return get(method.DeclaringType.Resolve()).argsMethodMapping[methodId];
		}

		// Token: 0x060000D4 RID: 212 RVA: 0x000053F4 File Offset: 0x000035F4
		private OverloadAnalyzer(TypeDefinition def, OverloadAnalyzer baseCache)
		{
			if (baseCache != null)
			{
				this.methodCounter = new Dictionary<string, int>(baseCache.methodCounter);
				this.argsMethodMapping = new Dictionary<string, string>(baseCache.argsMethodMapping);
			}
			foreach (MethodDefinition method in def.Methods)
			{
                this.methodCounter.TryGetValue(method.luaIdentifier(), out var count);
				count = this.methodCounter[method.luaIdentifier()] = count + 1;
				string nameArgsId = OverloadAnalyzer.getMethodId(method);
				string methodName;
				if (!this.argsMethodMapping.TryGetValue(nameArgsId, out methodName))
				{
					methodName = method.luaIdentifier();
					if(!method.GetCustomAttributeArguments(BuildConfig.nativeAttribute,ref methodName) && count > 1)
                    {
						methodName += count;
					}
					this.argsMethodMapping.Add(nameArgsId, methodName);
				}
			}
		}
		// Token: 0x060000D5 RID: 213 RVA: 0x000054F0 File Offset: 0x000036F0
		private static string getMethodId(MethodReference method)
		{
			string nameArgsId = method.luaIdentifier();
			string[] nameArgsIds = new string[method.Parameters.Count];
			for (int i = 0; i < method.Parameters.Count; i++)
			{
                ParameterDefinition parameterDefinition = method.Parameters[i];
                TypeDefinition paramType = parameterDefinition.ParameterType.Resolve();
				string paramTypeName;
				if (paramType == null)
				{
					paramTypeName = typeof(object).FullName;
				}
				else
				{
					paramTypeName = paramType.luaGlobalIdentifier();
				}
				nameArgsIds[i] = paramTypeName;
			}
			return $"{nameArgsId}({string.Join(",", nameArgsIds)})";
		}

		// Token: 0x04000063 RID: 99
		private Dictionary<string, int> methodCounter = new Dictionary<string, int>();

		// Token: 0x04000064 RID: 100
		private Dictionary<string, string> argsMethodMapping = new Dictionary<string, string>();

		// Token: 0x04000065 RID: 101
		private static Dictionary<string, OverloadAnalyzer> types = new Dictionary<string, OverloadAnalyzer>();
	}
}
